package com.sunshine.effctive.chapter02.item6;

import java.util.regex.Pattern;

/**
 * 判断输入的字符串是否是一个有效的罗马数字
 *
 * @author WeiHong
 * @date 2019/11/21 14:28
 */
public class RomanNumerals {

    /**
     * 该方法每次都内部为正则表达式创建一个 Pattern 实例，并且只使用它一次，之后它就有资格进行垃圾收集
     *
     * @param s
     * @return
     */
    public static boolean isRomanNumeralSlow(String s) {
        return s.matches("^(?=.)M*(C[MD]|D?C{0,3})"
                + "(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
    }


    private static final Pattern ROMAN = Pattern.compile(
            "^(?=.)M*(C[MD]|D?C{0,3})"
                    + "(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");

    /**
     * 为了提高性能，作为类初始化的一部分，将正则表达式显式编译为一个 Pattern 实例（不可变），缓存它，性能会大大的提升
     *
     * @param s
     * @return
     */
    public static boolean isRomanNumeralFast(String s) {
        return ROMAN.matcher(s).matches();
    }

    public static void main(String[] args) {
        int numSets = Integer.parseInt("100");
        int numReps = Integer.parseInt("100");
        boolean b = false;

        for (int i = 0; i < numSets; i++) {
            long start = System.nanoTime();
            for (int j = 0; j < numReps; j++) {
                b ^= isRomanNumeralFast("MCMLXXVI");
            }
            long end = System.nanoTime();
            System.out.println(((end - start) / (1_000. * numReps)) + " μs.");
        }

        if (!b) {
            System.out.println();
        }
    }


}
